import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { In, Repository } from 'typeorm';
import { Role } from './entities/role.entity';
import { CreateRoleDto } from './dto/create-role.dto';
import { UpdateRoleDto } from './dto/update-role.dto';
import { Permission } from '../permission/entities/permission.entity';
import { User } from '../user/entities/user.entity';
import * as path from 'node:path';
import { AppException } from '../exceptions/AppException';
import { HttpStatusCodeEnum } from '../enums/http-status-code.enum';
import { RoleData } from '../interface/role-data.interface';
import { AssignPermissionsDto } from './dto/assign-permissions.dto';
import { PermissionData } from '../interface/permission-data.interface';
import { PermissionService } from '../permission/permission.service';

@Injectable()
export class RoleService {
  private rolesFolderPath = path.join(
    process.cwd(),
    'src',
    'json',
    'role.enum.json',
  ); // 枚举文件夹路径
  private rolesPermissionFolderPath = path.join(
    process.cwd(),
    'src',
    'json',
    'role-permission.map.json',
  );

  constructor(
    @InjectRepository(Role)
    private readonly roleRepository: Repository<Role>,
    @InjectRepository(User)
    private readonly userRepository: Repository<User>,
    @InjectRepository(Permission)
    private readonly permissionRepository: Repository<Permission>,
    private readonly permissionService: PermissionService,
  ) {}

  // 创建角色
  async create(createRoleDto: CreateRoleDto): Promise<Role> {
    // 如果传递的是用户ID数组，转换为 User 实体数组
    if (createRoleDto.users && createRoleDto.users.length > 0) {
      createRoleDto.users = await this.userRepository.findByIds(
        createRoleDto.users,
      );
    }

    // 创建角色
    const role = this.roleRepository.create(createRoleDto);
    return this.roleRepository.save(role);
  }

  // 查询所有角色
  async findAll(): Promise<Role[]> {
    return this.roleRepository.find({ relations: ['permissions'] });
  }

  // 根据ID查询角色
  async findOne(id: string): Promise<Role> {
    return this.roleRepository.findOneById(id);
  }

  // 更新角色
  async update(id: string, updateRoleDto: UpdateRoleDto): Promise<Role> {
    await this.roleRepository.update(id, updateRoleDto);
    return this.roleRepository.findOneById(id);
  }

  // 删除角色
  async remove(id: string): Promise<void> {
    await this.roleRepository.delete(id);
  }

  // 批量创建角色
  async createBulk(createRoleDtos: CreateRoleDto[]): Promise<Role[]> {
    const roles = this.roleRepository.create(createRoleDtos);
    return await this.roleRepository.save(roles);
  }

  // 批量删除角色
  async removeBulk(ids: string[]): Promise<void> {
    await this.roleRepository.delete(ids);
  }

  // 为角色分配权限
  async assignPermissions(
    assignPermissionsDto: AssignPermissionsDto,
  ): Promise<Role> {
    const { roleId, permissions } = assignPermissionsDto;

    // 找到角色
    const role = await this.roleRepository.findOne({ where: { id: roleId } });
    if (!role) {
      throw new NotFoundException('角色未找到');
    }

    // 获取权限列表
    const permissionsList = await this.permissionRepository.find({
      relations: ['parent'],
      where: {
        id: In(permissions),
      },
    });

    if (permissionsList.length !== permissions.length) {
      throw new NotFoundException('一些权限未找到');
    }
    console.log('permissionsList', permissionsList);
    // 把权限列表组装成嵌套的
    const nestedPermissionsList =
      this.permissionService.buildPermissionHierarchyHelper(
        permissionsList,
        null,
      );
    console.log(
      'role.service.ts-assignPermissions-permissionList',
      nestedPermissionsList,
    );
    // 关联权限
    role.permissions = nestedPermissionsList;

    // 保存角色和权限的关联关系
    await this.roleRepository.save(role);

    return role;
  }

  async importRoles(): Promise<string> {
    const rolesData: RoleData[] = []; // 用于存储角色数据
    // 动态导入角色文件
    const roleModule = await import(this.rolesFolderPath);
    try {
      // console.log('Importing Role Module:', roleModule);

      for (const roleModuleObj of roleModule) {
        rolesData.push({
          name: roleModuleObj['enum_value'],
          description: roleModuleObj['description'],
        });
      }
    } catch (error) {
      console.error('Error importing role file:', error);
    }

    try {
      // 清空数据库中的角色数据
      await this.clearRoles();
    } catch (error) {
      console.log('role.service.ts-importRoles-error', error);
      throw new AppException(HttpStatusCodeEnum.FOREIGN_KEY_ERROR);
    }

    // 将导入的角色数据保存到数据库
    const roles = this.roleRepository.create(rolesData);

    await this.roleRepository.save(roles);

    return 'Roles imported successfully';
  }

  /**
   * 清空数据权限以及其依赖
   * @returns {Promise<void>}
   */
  async clearRoles(): Promise<void> {
    const queryRunner =
      this.roleRepository.manager.connection.createQueryRunner();

    await queryRunner.startTransaction();

    try {
      // 删除角色表中的所有记录
      await queryRunner.query('DELETE FROM role'); // 删除所有角色

      // 提交事务
      await queryRunner.commitTransaction();

      console.log('角色数据已成功清空');
    } catch (error) {
      // 回滚事务
      await queryRunner.rollbackTransaction();
      console.error('清空角色数据时出错:', error);
    } finally {
      // 释放查询执行器
      await queryRunner.release();
    }
  }

  async hardDelete(id: string): Promise<void> {
    const role = await this.findOne(id);
    await this.roleRepository.remove(role); // 从数据库中完全删除
  }
}
